// =================================================================
// File: Superblock.cpp
// Desc: Contains implementations for Superblock class functions
// =================================================================

// =================================================================
// INCLUDES
// =================================================================

#include "Superblock.h"
#include "config.h"

// =================================================================
// FUNCTIONS
// =================================================================

// =================================================================
// Name: Superblock::Superblock
// Desc: Initializes a superblock with given attributes
// Args: int fs_size - size of filesystem
//       int block_size - size of a block
//       int num_inodes - total number of inodes in filesystem
// =================================================================
Superblock::Superblock(int fs_size, int block_size,	int num_inodes) :
    fs_size(fs_size), block_size(block_size), num_inodes(num_inodes)
{
    // Calculate number of blocks left in file system
    int leftover_space = fs_size - ((num_inodes*INODE_SIZE) + SB_BK + (INT_SIZE*NUM_INODES));
    this->num_data_blocks = leftover_space / (block_size + INT_SIZE);

    // Calculate offsets
    this->inodes_offset = SB_BK + num_inodes*INT_SIZE + this->num_data_blocks*INT_SIZE;

    this->blocks_offset = this->inodes_offset + num_inodes*INODE_SIZE;
    this->blocks_offset += this->blocks_offset % block_size;
}

// =================================================================
// Name: Superblock::Superblock
// Desc: Initializes Superblock with values from config.h
// =================================================================
Superblock::Superblock()
{
    Superblock(FS_SIZE,BLOCK_SIZE,NUM_INODES);
}

// =================================================================
// Name: Superblock::~Superblock
// Desc: Superblock destructor
// =================================================================
Superblock::~Superblock()
{
}

// =================================================================
// Name: Superblock::FreeInodePop
// Desc: removes the first inode from the list and returns its index
// Rets: inode index popped off
// =================================================================
int Superblock::FreeInodePop()
{
	if(!free_inodes.empty()){
		int index = free_inodes[0];
		free_inodes.erase(free_inodes.begin());
		return index;
	}
	else{
		cerr << "NO FREE INODES REMAINING!!" << endl;
		exit(1);
	}
}

// =================================================================
// Name: Superblock::FreeDataBlockPop
// Desc: removes the first free block from list and returns index
// Rets: index of popped block
// =================================================================
int Superblock::FreeDataBlockPop()
{
	if(!free_inodes.empty()){
		int index = free_blocks[0];
		free_blocks.erase(free_blocks.begin());
		return index;
	}
	else{
		cerr << "NO FREE DATA BLOCKS REMAINING!!" << endl;
		exit(1);
	}
}